<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>Qt 4.3: glwidget.cpp Example File (opengl/pbuffers2/glwidget.cpp)</title>
  <link href="classic.css" rel="stylesheet" type="text/css" />
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td align="left" valign="top" width="32"><a href="http://www.trolltech.com/products/qt"><img src="images/qt-logo.png" align="left" width="32" height="32" border="0" /></a></td>
<td width="1">&nbsp;&nbsp;</td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a>&nbsp;&middot; <a href="classes.html"><font color="#004faf">All&nbsp;Classes</font></a>&nbsp;&middot; <a href="mainclasses.html"><font color="#004faf">Main&nbsp;Classes</font></a>&nbsp;&middot; <a href="groups.html"><font color="#004faf">Grouped&nbsp;Classes</font></a>&nbsp;&middot; <a href="modules.html"><font color="#004faf">Modules</font></a>&nbsp;&middot; <a href="functions.html"><font color="#004faf">Functions</font></a></td>
<td align="right" valign="top" width="230"><a href="http://www.trolltech.com"><img src="images/trolltech-logo.png" align="right" width="203" height="32" border="0" /></a></td></tr></table><h1 align="center">glwidget.cpp Example File<br /><sup><sup>opengl/pbuffers2/glwidget.cpp</sup></sup></h1>
<pre><span class="comment"> /****************************************************************************
 **
 ** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
 **
 ** This file is part of the documentation of the Qt Toolkit.
 **
 ** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by Trolltech ASA
** (or its successors, if any) and the KDE Free Qt Foundation. 
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
** you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** In addition, as a special exception, Trolltech, as the sole
** copyright holder for Qt Designer, grants users of the Qt/Eclipse
** Integration plug-in the right for the Qt/Eclipse Integration to
** link to functionality provided by Qt Designer and its related
** libraries.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
** granted herein.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ****************************************************************************/</span>

 #include &lt;QtGui/QImage&gt;
 #include &quot;glwidget.h&quot;

 #include &lt;math.h&gt;

 #ifndef GL_MULTISAMPLE
 #define GL_MULTISAMPLE  0x809D
 #endif

 GLWidget::GLWidget(QWidget *parent)
     : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
 {
     setWindowTitle(tr(&quot;OpenGL pbuffers 2&quot;));

     pbuffer = new QGLPixelBuffer(512, 512, format(), this);

     rot_x = rot_y = rot_z = 0.0f;
     scale = 0.1f;
     anim = new QTimeLine(750, this);
     anim-&gt;setUpdateInterval(20);
     connect(anim, SIGNAL(valueChanged(qreal)), SLOT(animate(qreal)));
     connect(anim, SIGNAL(finished()), SLOT(animFinished()));

     svg_renderer = new QSvgRenderer(QLatin1String(&quot;:/res/bubbles.svg&quot;), this);
     connect(svg_renderer, SIGNAL(repaintNeeded()), this, SLOT(draw()));

     logo = QImage(&quot;:/res/qt4-logo.png&quot;);
     logo = logo.convertToFormat(QImage::Format_ARGB32);

     makeCurrent(); <span class="comment">//</span> need a current context to create the display list
     tile_list = glGenLists(1);
     glNewList(tile_list, GL_COMPILE);
     glBegin(GL_QUADS);
     {
         glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
         glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
         glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
         glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);

         glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
         glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
         glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
         glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);

         glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
         glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
         glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
         glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);

         glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
         glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
         glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
         glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);

         glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
         glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
         glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
         glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);

         glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
         glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
         glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
         glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
 }
     glEnd();
     glEndList();

     wave = new GLfloat[logo.width()*logo.height()];
     memset(wave, 0, logo.width()*logo.height());
     startTimer(30); <span class="comment">//</span> wave timer

     pbuffer-&gt;makeCurrent();
     dynamicTexture = pbuffer-&gt;generateDynamicTexture();

     <span class="comment">//</span> bind the dynamic texture to the pbuffer - this is a no-op under X11
     pbuffer-&gt;bindToDynamicTexture(dynamicTexture);
 }

 GLWidget::~GLWidget()
 {
     delete[] wave;
     glDeleteLists(tile_list, 1);
     pbuffer-&gt;releaseFromDynamicTexture();
     glDeleteTextures(1, &amp;dynamicTexture);
     delete pbuffer;
 }

 void GLWidget::paintEvent(QPaintEvent *)
 {
     draw();
 }

 void GLWidget::draw()
 {
     QPainter p(this); <span class="comment">//</span> used for text overlay

     <span class="comment">//</span> save the GL state set for QPainter
     saveGLState();

     <span class="comment">//</span> render the 'bubbles.svg' file into our pbuffer
     QPainter pbuffer_painter(pbuffer);
     svg_renderer-&gt;render(&amp;pbuffer_painter);
     pbuffer_painter.end();
     glFlush();

 #if  defined(Q_WS_X11)
     <span class="comment">//</span> rendering directly to a texture is not supported on X11, unfortunately
     pbuffer-&gt;updateDynamicTexture(dynamicTexture);
 #endif

     makeCurrent();
     <span class="comment">//</span> draw into the GL widget
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glFrustum(-1, 1, -1, 1, 10, 100);
     glTranslatef(0.0f, 0.0f, -15.0f);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glViewport(0, 0, width(), height());

     glBindTexture(GL_TEXTURE_2D, dynamicTexture);
     glEnable(GL_TEXTURE_2D);
     glEnable(GL_MULTISAMPLE);
     glEnable(GL_CULL_FACE);
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

     <span class="comment">//</span> draw background
     glPushMatrix();
     glScalef(1.7f, 1.7f, 1.7f);
     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     glCallList(tile_list);
     glPopMatrix();

     const int w = logo.width();
     const int h = logo.height();

     glRotatef(rot_x, 1.0f, 0.0f, 0.0f);
     glRotatef(rot_y, 0.0f, 1.0f, 0.0f);
     glRotatef(rot_z, 0.0f, 0.0f, 1.0f);
     glScalef(scale/w, scale/w, scale/w);

     glDepthFunc(GL_LESS);
     glEnable(GL_DEPTH_TEST);

     <span class="comment">//</span> draw the Qt icon
     glTranslatef(-w+1, -h+1, 0.0f);
     for (int y=h-1; y&gt;=0; --y) {
         uint *p = (uint*) logo.scanLine(y);
         uint *end = p + w;
         int  x = 0;
         while (p &lt; end) {
             glColor4ub(qRed(*p), qGreen(*p), qBlue(*p), uchar(qAlpha(*p)*.9));
             glTranslatef(0.0f, 0.0f, wave[y*w+x]);
             if (qAlpha(*p) &gt; 128)
                 glCallList(tile_list);
             glTranslatef(0.0f, 0.0f, -wave[y*w+x]);
             glTranslatef(2.0f, 0.0f, 0.0f);
             ++x;
             ++p;
         }
         glTranslatef(-w*2.0f, 2.0f, 0.0f);
     }

     <span class="comment">//</span> restore the GL state that QPainter expects
     restoreGLState();

     <span class="comment">//</span> draw the overlayed text using QPainter
     p.setPen(QColor(197, 197, 197, 157));
     p.setBrush(QColor(197, 197, 197, 127));
     p.drawRect(QRect(0, 0, width(), 50));
     p.setPen(Qt::black);
     p.setBrush(Qt::NoBrush);
     const QString str1(tr(&quot;A simple OpenGL pbuffer example.&quot;));
     const QString str2(tr(&quot;Use the mouse wheel to zoom, press buttons and move mouse to rotate, double-click to flip.&quot;));
     QFontMetrics fm(p.font());
     p.drawText(width()/2 - fm.width(str1)/2, 20, str1);
     p.drawText(width()/2 - fm.width(str2)/2, 20 + fm.lineSpacing(), str2);
 }

 void GLWidget::mousePressEvent(QMouseEvent *e)
 {
     anchor = e-&gt;pos();
 }

 void GLWidget::mouseMoveEvent(QMouseEvent *e)
 {
     QPoint diff = e-&gt;pos() - anchor;
     if (e-&gt;buttons() &amp; Qt::LeftButton) {
         rot_x += diff.y()/5.0f;
         rot_y += diff.x()/5.0f;
     } else if (e-&gt;buttons() &amp; Qt::RightButton) {
         rot_z += diff.x()/5.0f;
     }

     anchor = e-&gt;pos();
     draw();
 }

 void GLWidget::wheelEvent(QWheelEvent *e)
 {
     e-&gt;delta() &gt; 0 ? scale += scale*0.1f : scale -= scale*0.1f;
     draw();
 }

 void GLWidget::mouseDoubleClickEvent(QMouseEvent *)
 {
     anim-&gt;start();
 }

 void GLWidget::animate(qreal val)
 {
     rot_y = val * 180;
     draw();
 }

 void GLWidget::animFinished()
 {
     if (anim-&gt;direction() == QTimeLine::Forward)
         anim-&gt;setDirection(QTimeLine::Backward);
     else
         anim-&gt;setDirection(QTimeLine::Forward);
 }

 void GLWidget::saveGLState()
 {
     glPushAttrib(GL_ALL_ATTRIB_BITS);
     glMatrixMode(GL_PROJECTION);
     glPushMatrix();
     glMatrixMode(GL_MODELVIEW);
     glPushMatrix();
 }

 void GLWidget::restoreGLState()
 {
     glMatrixMode(GL_PROJECTION);
     glPopMatrix();
     glMatrixMode(GL_MODELVIEW);
     glPopMatrix();
     glPopAttrib();
 }

 #define PI 3.14159

 void GLWidget::timerEvent(QTimerEvent *)
 {
     if (QApplication::mouseButtons() != 0)
         return;

     static bool scale_in = true;

     if (scale_in &amp;&amp; scale &gt; 35.0f)
         scale_in = false;
     else if (!scale_in &amp;&amp; scale &lt; .5f)
         scale_in = true;

     scale = scale_in ? scale + scale*0.01f : scale-scale*0.01f;
     rot_z += 0.3f;
     rot_x += 0.1f;

     int dx, dy; <span class="comment">//</span> disturbance point
     float s, v, W, t;
     int i, j;
     static float wt[128][128];
     const int width = logo.width();
     const int AMP = 5;

     dx = dy = width &gt;&gt; 1;

     W = .3f;
     v = -4; <span class="comment">//</span> wave speed

     for (i = 0; i &lt; width; ++i) {
         for ( j = 0; j &lt; width; ++j) {
             s = sqrt((double) ((j - dx) * (j - dx) + (i - dy) * (i - dy)));
             wt[i][j] += 0.1f;
             t = s / v;
             if (s != 0)
                 wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t)) / (0.2*(s + 2));
             else
                 wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t));
         }
     }
 }</pre>
<p /><address><hr /><div align="center">
<table width="100%" cellspacing="0" border="0"><tr class="address">
<td width="30%">Copyright &copy; 2008 <a href="trolltech.html">Trolltech</a></td>
<td width="40%" align="center"><a href="trademarks.html">Trademarks</a></td>
<td width="30%" align="right"><div align="right">Qt 4.3.5</div></td>
</tr></table></div></address></body>
</html>
